package com.tang.utils;

import com.alibaba.fastjson.JSONObject;
import com.tang.config.JwtAuthorizationConfig;
import com.tang.domian.SxToken;
import com.tang.domian.Token;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.Builder;

import java.security.SignatureException;
import java.time.Instant;
import java.util.Date;
import java.util.UUID;

/**
 * @ClassName: JwtUtil
 * @Description: jwt生成token工具类和验证工具类
 * @date: 2019/7/12
 */
@Builder
public class JwtUtil {

    /**
     * 签发token
     *
     * @return
     */
    public static String create(JwtAuthorizationConfig config, Token user) {
        return Jwts.builder()
                .signWith(SignatureAlgorithm.HS512, config.getSecret())
                .setSubject(String.valueOf(user.getUserId()))
                .claim(config.getInfo(), user)
                .setIssuedAt(Date.from(Instant.now()))
                .setExpiration(Date.from(Instant.now().plusSeconds(config.getExpiration())))
                .compact();
    }

    /**
     * 签发refreshToken，移动端的登录会话保持
     *
     * @param config
     * @param user
     * @return
     */
    public static String createRefreshToken(JwtAuthorizationConfig config, Token user) {
        return Jwts.builder()
                .signWith(SignatureAlgorithm.HS512, config.getSecret())
                .setSubject(String.valueOf(user.getUserId()))
                .claim("self", UUID.randomUUID())
                .setIssuedAt(Date.from(Instant.now()))
                .setExpiration(Date.from(Instant.now().plusSeconds(config.getRefreshExpiration())))
                .compact();
    }

    /**
     * 解析token
     *
     * @param secret
     * @param token
     * @return
     */
    public static Claims parse(String secret, String token) throws SignatureException {
        return Jwts.parser()
                .setSigningKey(secret)
                .parseClaimsJws(token)
                .getBody();
    }

    /**
     * 获取Token用户信息
     *
     * @param config
     * @param token
     * @return
     * @throws SignatureException
     */
    public static Token getToken(JwtAuthorizationConfig config, String token) throws Exception {
        Claims claims = Jwts.parser()
                .setSigningKey(config.getSecret())
                .parseClaimsJws(token)
                .getBody();
        return JSONObject.toJavaObject(JSONObject.parseObject(JSONObject.toJSONString(claims.get(config.getInfo()))), Token.class);
    }

    /**
     * 兼容VACA应用
     */
    public static SxToken getSxToken(JwtAuthorizationConfig config, String token) throws Exception {
        Claims claims = Jwts.parser()
                .setSigningKey(config.getSecret())
                .parseClaimsJws(token)
                .getBody();
        return JSONObject.toJavaObject(JSONObject.parseObject(JSONObject.toJSONString(claims.get(config.getInfo()))), SxToken.class);
    }

    /**
     * 验证是否有效token
     *
     * @param token
     * @return
     */
    public static Boolean isValid(JwtAuthorizationConfig config, String token) throws SignatureException {
        Claims claims = parse(config.getSecret(), token);
        Integer userId = Integer.parseInt(claims.getSubject());
        if (userId != null) {
            return true;
        }
        return false;
    }

    /**
     * 检查token是否过期
     *
     * @param config
     * @param token
     * @return
     */
    public static Boolean isTokenExpired(JwtAuthorizationConfig config, String token) throws SignatureException {
        Claims claims = parse(config.getSecret(), token);
        final Date expireTime = claims.getExpiration();
        return expireTime.before(Date.from(Instant.now()));
    }

    public static Date getExpireTime(JwtAuthorizationConfig config, String token) throws SignatureException {
        Claims claims = parse(config.getSecret(), token);
        final Date expireTime = claims.getExpiration();
        return expireTime;
    }

    /**
     * 重新设置过期时间
     *
     * @param config
     * @param token
     */
    public static String resetExpire(JwtAuthorizationConfig config, String token) throws SignatureException {
        Claims claims = parse(config.getSecret(), token);
        claims.setExpiration(Date.from(Instant.now().plusSeconds(config.getExpiration())));
        return Jwts.builder().setClaims(claims).compact();
    }

}
